package com.xiongmao.webflux.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.xiongmao.webflux.auth.entity.SysUser;
import com.xiongmao.webflux.auth.dao.SysUserDao;
import com.xiongmao.webflux.auth.entity.vo.LoginUserInfo;
import com.xiongmao.webflux.auth.entity.vo.SysUserVo;
import com.xiongmao.webflux.auth.service.SysUserService;
import com.xiongmao.webflux.common.CommonConst;
import com.xiongmao.webflux.common.ResponseData;
import com.xiongmao.webflux.common.cookies.CookiesUtils;
import com.xiongmao.webflux.common.language.ErrorMsgEnum;
import com.xiongmao.webflux.utils.RedisUtils;
import com.xiongmao.webflux.utils.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

/**
 * 用户信息表(SysUser)表服务实现类
 *
 * @author makejava
 * @since 2022-02-25 14:34:41
 */
@Service("sysUserService")
public class SysUserServiceImpl implements SysUserService {
    @Resource
    private SysUserDao sysUserDao;
    @Autowired
    private RedisUtils redisUtils;

    @Override
    public ResponseEntity<ResponseData> doLogin(LoginUserInfo userInfo) {
        String username = userInfo.getUsername();
        String password = userInfo.getPassword();
        ResponseEntity<ResponseData> stringResponseEntity = login(username,password);
        return stringResponseEntity;
    }

    @Override
    public Mono<ResponseEntity<ResponseData>> formLogin(ServerWebExchange exchange) {
        return exchange.getFormData().map(map ->{
            String username=map.getFirst("username");
            String password = map.getFirst("password");
            if(StringUtil.isBlank(username) || StringUtil.isBlank(password)){
                getErrorResponse("");
            }
            ResponseEntity<ResponseData> stringResponseEntity = login(username, password);
            return stringResponseEntity;
        });
    }

    @Override
    public ResponseEntity<ResponseData> registerByEmail(LoginUserInfo userInfo) {
        return null;
    }

    @Override
    public ResponseEntity<ResponseData> registerByPhone(LoginUserInfo userInfo) {
        return null;
    }

    /**
     * 登录统一处理
     */
    private ResponseEntity<ResponseData> login(String username,String password){
        ResponseEntity<ResponseData> entity;
        //身份验证
        SysUser sysUser = sysUserDao.selectUserInfo(username);
        if(!password.equals(sysUser.getPassword())){
            entity = getErrorResponse(ErrorMsgEnum.CHECK_YOUR_CREDENTIALS.getMsg());
            return entity;
        }
        SysUserVo sysUserVo = new SysUserVo();
        BeanUtils.copyProperties(sysUser,sysUserVo);
        // TODO 缓存用户及权限信息
        Set<String> permissions = new HashSet<>();
        Set<Integer> roles = new HashSet<>();
        sysUserVo.setPermissions(permissions);
        sysUserVo.setRoles(roles);
        return getSuccessResponse(sysUserVo);
    }

    private ResponseEntity<ResponseData> getErrorResponse(String errorMsg) {
        String sid = UUID.randomUUID().toString().replace("-", "");
        //自定义cookies信息到前端
        HttpHeaders headers = CookiesUtils.getCookie(sid);
        ResponseEntity<ResponseData> entity = new ResponseEntity<>(ResponseData.fail(errorMsg), headers, HttpStatus.UNAUTHORIZED);
        return entity;
    }

    private ResponseEntity<ResponseData> getSuccessResponse(SysUserVo sysUserVo) {
        String sid = UUID.randomUUID().toString().replace("-", "");
        //自定义cookies信息到前端
        HttpHeaders headers = CookiesUtils.getCookie(sid);
        redisUtils.set(CommonConst.SESSION_CACHE + sid, JSON.toJSONString(sysUserVo));
        ResponseEntity<ResponseData> entity = new ResponseEntity<>(ResponseData.ok(), headers, HttpStatus.OK);
        return entity;
    }
}